
function ImageObject(img, offset, isMaskTest)
{
    if (this instanceof ImageObject)
    {
        this.img = img;
        this.offset = new Point(0, 0);
        this._supportHitTest = false;
        if (offset)
        {
            this.offset.setValue(offset);
        }
        this.aabb = new Rect(0, 0, 0, 0);
        this.isMaskTest = false;
        if (isMaskTest !== undefined)
        {
            this._supportHitTest = true;
            this.isMaskTest = isMaskTest;
        }
    }
    else
    {
        return new ImageObject(img, offset, isMaskTest);
    }
}

ImageObject.prototype.setOffset = function(offset)
{
	this.offset.setValue(offset);
}

ImageObject.prototype.getOffset = function()
{
	return this.offset;
}

ImageObject.prototype.isSupportHitTest = function()
{
	return this._supportHitTest && (!!this.img);
}

ImageObject.prototype.updateImg = function(img)
{
	this.img = img;
}

ImageObject.prototype.setAabb = function(aabb)
{
	this.aabb.setValue(aabb);
}

ImageObject.prototype.hitTest = function(pt)
{
    var localPt = Point.s_sub(pt, this.offset);
	if (this.isMaskTest)
	{
		return this.img.testNotAlpha(localPt);
	}
	else
	{

		return this.aabb.hitTest(localPt);
	}
}

ImageObject.prototype.draw = function(ctx, x, y)
{
	if (this.img)
		this.img.draw(ctx, this.offset.x + x, this.offset.y + y);
}
// this aabb test is to image render test. so will be larger.
ImageObject.prototype.TestAabb = function(aabb)
{
    return this.aabb.isIntersect(Rect.s_subPoint(aabb, this.offset));
}

function FarmTipWindow()
{
    if (this instanceof FarmTipWindow)
    {
        this._isActive = false;
        this.pos = new Point(0, 0);
        this.text = "";
        this.backColor = "rgba(255, 255, 255, 0.2)";
        this.textColor = "rgba(0, 0, 0, 1)";
        this.region = new Rect(0, 0);
        this.font = "";
        this.fontHeight = 10;
    }
    else
    {
        return new FarmTipWindow();
    }
}

FarmTipWindow.prototype.setBackColor = function(backColor)
{
	this.backColor = backColor;
}

FarmTipWindow.prototype.setTextColor = function(textColor)
{
	this.textColor = textColor;
}

FarmTipWindow.prototype.setFont = function(font, fontHeight)
{
	this.font = font;
	this.fontHeight = fontHeight;
}

FarmTipWindow.prototype.setActive = function(active)
{
	this._isActive = active;
}

FarmTipWindow.prototype.isActive = function()
{
	return this._isActive;
}

FarmTipWindow.prototype.isSupportHitTest = function()
{
	return false;
}

FarmTipWindow.prototype.draw = function(ctx, x, y)
{
	if (!this.isActive()) return;
	if (this.text == "") return;
	var metrix = ctx.measureText(this.text);
    var numRows = Math.floor(metrix.width / 200) + 1;
	var fontW = (metrix.width > 200 ? 200 : metrix.width) + 8;
	var fontH = (this.fontHeight + 2) * numRows + 6;
	ctx.fillStyle = this.backColor;
	ctx.strokeStyle = this.textColor;
	ctx.textBaseline = "top";
	y -= fontH;
    ctx.fillRect(x - fontW / 2, y, fontW, fontH);
	var font = ctx.font;
	if (this.font != "")
	{
		ctx.font = this.font;
	}
    var startIndex = 0;
    var numCharInRow = Math.floor(this.text.length / numRows);
    for (var i = 0; i < numRows; i++)
    {
        var tempStr = "";
        if (i == numRows - 1)
        {
            tempStr = this.text.slice(startIndex);
        }
        else
        {
            tempStr = this.text.slice(startIndex, startIndex + numCharInRow);
        }
        ctx.strokeText(tempStr, x + 1 - fontW / 2, y + 2 + (this.fontHeight + 2) * i);
        startIndex += numCharInRow;
    }
	ctx.font = font;
}

FarmTipWindow.prototype.setPosition = function(pos)
{
	this.pos.setValue(pos);
}

FarmTipWindow.prototype.setColor = function(backColor)
{
	this.backColor = backColor;
}

FarmTipWindow.prototype.setText = function(text)
{
	this.text = text;
}

function FloatingTip()
{
    if (this instanceof FloatingTip)
    {
        this.track = null;
        this.tipWindow = null;
        this.node = null;
    }
    else
    {
        return new FloatingTip();
    }
}

FloatingTip.prototype.start = function()
{
    this.tipWindow.setActive(true);
    this.track.start();
}

FloatingTip.prototype.update = function(interval)
{
	if (this.tipWindow.isActive())
	{
		this.track.update(interval);
		if (this.track.isEnd())
		{
		    if (this.node)
		    {
		        this.node.detach();
		        this.node = null;
		    }
			this.tipWindow.setActive(false);
		}
	}
}

FloatingTip.prototype.draw = function(ctx)
{
	if (this.tipWindow.isActive())
	{
		if (this.node)
		{
		    // draw by scene.
		}
		else
		{
	    	var pos = this.track.getOffset();
		    this.tipWindow.draw(ctx, pos.x, pos.y);
		}
	}
}

FloatingTip.prototype.setValue = function(startPos, endPos, time, text, parentNode)
{
    this.track = new MoveTrack(startPos, endPos, time, false);
    if (!this.tipWindow)
    {
        this.tipWindow = new FarmTipWindow();
    }
    this.tipWindow.setText(text);
    if (parentNode)
    {
        this.node = new SceneNode(parentNode, this.tipWindow);
        this.node.enableHitTest(false);
        this.node.setTrack(this.track);
    }
}

FloatingTip.prototype.isActive = function()
{
	return this.tipWindow.isActive();
}

// display rising tip manager
function FloatingTipManager(time, offset)
{
	this.time = time;
    this.offset = offset.clone();
	this.tipList = [];
}

FloatingTipManager.prototype.findTip = function()
{
	for (var i = 0; i < this.tipList.length; i++)
	{
		if (!this.tipList[i].isActive())
			return this.tipList[i];
	}
	var tip = new FloatingTip();
	this.tipList.push(tip);
	return tip;
}

FloatingTipManager.prototype.startTip = function(pos, text, parentNode)
{
	var tip = this.findTip();
	tip.setValue(pos, Point.s_add(pos, this.offset), this.time, text, parentNode);
	tip.start();
}

FloatingTipManager.prototype.update = function(interval)
{
	var len = this.tipList.length;
	for (var i = 0; i < len; i++)
	{
		this.tipList[i].update(interval);
	}
}

FloatingTipManager.prototype.draw = function(ctx)
{
	var len = this.tipList.length;
	for (var i = 0; i < len; i++)
	{
		this.tipList[i].draw(ctx);
	}
}